package com.bf.electroplating.util.word;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

/**
 * Word文档批量处理器
 * 负责批量处理文件夹中的Word文档
 */
@Slf4j
@Component
public class WordDocumentBatchProcessor {
    
    private final WordDocumentParser documentParser;
    private final WordImageExtractor imageExtractor;
    private final WordRectificationDataProcessor dataProcessor;
    
    public WordDocumentBatchProcessor(WordDocumentParser documentParser,
                                    WordImageExtractor imageExtractor,
                                    WordRectificationDataProcessor dataProcessor) {
        this.documentParser = documentParser;
        this.imageExtractor = imageExtractor;
        this.dataProcessor = dataProcessor;
    }
    
    /**
     * 批量处理文件夹中的Word文档
     * @param folderPath 文件夹路径
     * @return 处理结果汇总
     */
    public BatchProcessResult processFolder(String folderPath) {
        BatchProcessResult batchResult = new BatchProcessResult();
        batchResult.setFolderPath(folderPath);
        
        try {
            log.info("开始批量处理Word文档，文件夹: {}", folderPath);
            
            // 1. 扫描Word文档
            List<String> wordFiles = scanWordFiles(folderPath);
            if (wordFiles.isEmpty()) {
                batchResult.setSuccess(false);
                batchResult.setErrorMessage("文件夹中未找到Word文档(.docx文件)");
                return batchResult;
            }
            
            log.info("找到{}个Word文档", wordFiles.size());
            batchResult.setTotalFiles(wordFiles.size());
            
            // 2. 逐个处理文档
            List<WordDocumentParser.WordDocumentData> allDocuments = new ArrayList<>();
            Map<String, Map<String, String>> allImageMaps = new HashMap<>();
            
            for (String filePath : wordFiles) {
                try {
                    log.info("正在处理文档: {}", filePath);
                    
                    // 解析文档
                    WordDocumentParser.WordDocumentData documentData = documentParser.parseDocument(filePath);
                    
                    if (documentData.hasError()) {
                        log.error("文档解析失败: {} - {}", filePath, documentData.getError());
                        batchResult.addFailedFile(filePath, documentData.getError());
                        continue;
                    }
                    
                    // 提取图片
                    Map<String, String> imageMap = extractImagesFromDocument(filePath);
                    
                    allDocuments.add(documentData);
                    allImageMaps.put(filePath, imageMap);
                    
                    batchResult.addSuccessFile(filePath, documentData.getCompanyName());
                    
                } catch (Exception e) {
                    log.error("处理文档失败: {}", filePath, e);
                    batchResult.addFailedFile(filePath, "处理异常: " + e.getMessage());
                }
            }
            
            // 3. 批量保存数据
            if (!allDocuments.isEmpty()) {
                log.info("开始批量保存{}个文档的数据", allDocuments.size());
                List<WordRectificationDataProcessor.WordProcessResult> results = 
                    dataProcessor.processDocuments(allDocuments, allImageMaps);
                
                // 统计结果
                int totalSuccess = 0;
                int totalFail = 0;
                for (WordRectificationDataProcessor.WordProcessResult result : results) {
                    if (result.isSuccess()) {
                        totalSuccess += result.getSuccessCount();
                        totalFail += result.getFailCount();
                    } else {
                        batchResult.addFailedFile(result.getDocumentPath(), result.getErrorMessage());
                    }
                }
                
                batchResult.setTotalRecords(totalSuccess + totalFail);
                batchResult.setSuccessRecords(totalSuccess);
                batchResult.setFailRecords(totalFail);
                
                log.info("批量处理完成: 成功{}条，失败{}条", totalSuccess, totalFail);
            }
            
            batchResult.setSuccess(true);
            
        } catch (Exception e) {
            batchResult.setSuccess(false);
            batchResult.setErrorMessage("批量处理异常: " + e.getMessage());
            log.error("批量处理Word文档异常", e);
        }
        
        return batchResult;
    }
    
    /**
     * 扫描文件夹中的Word文档
     */
    private List<String> scanWordFiles(String folderPath) {
        List<String> wordFiles = new ArrayList<>();
        
        try {
            File folder = new File(folderPath);
            if (!folder.exists() || !folder.isDirectory()) {
                log.error("文件夹不存在或不是目录: {}", folderPath);
                return wordFiles;
            }
            
            File[] files = folder.listFiles((dir, name) -> {
                String lowerName = name.toLowerCase();
                return lowerName.endsWith(".docx") && !lowerName.startsWith("~");
            });
            
            if (files != null) {
                for (File file : files) {
                    wordFiles.add(file.getAbsolutePath());
                }
                // 按文件名排序
                wordFiles.sort(String::compareTo);
            }
            
        } catch (Exception e) {
            log.error("扫描Word文件失败: {}", folderPath, e);
        }
        
        return wordFiles;
    }
    
    /**
     * 从文档中提取图片
     */
    private Map<String, String> extractImagesFromDocument(String filePath) {
        Map<String, String> imageMap = new HashMap<>();
        
        try (FileInputStream fis = new FileInputStream(filePath);
             XWPFDocument document = new XWPFDocument(fis)) {
            
            String fileName = new File(filePath).getName();
            
            // 提取所有图片
            Map<String, String> allImages = imageExtractor.extractAllImages(document, fileName);
            
            // 将图片与表格行关联
            Map<String, String> rowImages = imageExtractor.associateImagesWithRows(document, allImages);
            
            imageMap.putAll(rowImages);
            
        } catch (IOException e) {
            log.error("提取图片失败: {}", filePath, e);
        }
        
        return imageMap;
    }
    
    /**
     * 验证文件夹路径
     */
    public boolean validateFolderPath(String folderPath) {
        if (folderPath == null || folderPath.trim().isEmpty()) {
            return false;
        }
        
        File folder = new File(folderPath);
        return folder.exists() && folder.isDirectory();
    }
    
    /**
     * 获取文件夹中的Word文档数量
     */
    public int getWordFileCount(String folderPath) {
        return scanWordFiles(folderPath).size();
    }
    
    /**
     * 预览企业匹配情况
     */
    public Map<String, String> previewCompanyMatching(String folderPath) {
        Map<String, String> matchingResults = new HashMap<>();
        
        try {
            List<String> wordFiles = scanWordFiles(folderPath);
            
            for (String filePath : wordFiles) {
                try {
                    WordDocumentParser.WordDocumentData documentData = documentParser.parseDocument(filePath);
                    
                    if (!documentData.hasError()) {
                        String fileName = new File(filePath).getName();
                        String companyName = documentData.getCompanyName();
                        
                        // 这里可以添加企业匹配逻辑，暂时返回公司名称
                        matchingResults.put(fileName, companyName);
                    }
                } catch (Exception e) {
                    log.warn("预览文档失败: {}", filePath, e);
                    matchingResults.put(new File(filePath).getName(), "解析失败");
                }
            }
            
        } catch (Exception e) {
            log.error("预览企业匹配失败", e);
        }
        
        return matchingResults;
    }
    
    /**
     * 批量处理结果
     */
    public static class BatchProcessResult {
        private boolean success;
        private String folderPath;
        private int totalFiles;
        private int successFiles;
        private int failFiles;
        private int totalRecords;
        private int successRecords;
        private int failRecords;
        private int matchedCompanyCount;  // 匹配到企业的数量
        private int unmatchedCompanyCount; // 未匹配到企业的数量
        private List<String> successFileList;
        private List<String> failedFileList;
        private Map<String, String> failedReasons;
        private String errorMessage;
        
        public BatchProcessResult() {
            this.successFileList = new ArrayList<>();
            this.failedFileList = new ArrayList<>();
            this.failedReasons = new HashMap<>();
        }
        
        // Getters and Setters
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        
        public String getFolderPath() { return folderPath; }
        public void setFolderPath(String folderPath) { this.folderPath = folderPath; }
        
        public int getTotalFiles() { return totalFiles; }
        public void setTotalFiles(int totalFiles) { this.totalFiles = totalFiles; }
        
        public int getSuccessFiles() { return successFiles; }
        public void setSuccessFiles(int successFiles) { this.successFiles = successFiles; }
        
        public int getFailFiles() { return failFiles; }
        public void setFailFiles(int failFiles) { this.failFiles = failFiles; }
        
        public int getTotalRecords() { return totalRecords; }
        public void setTotalRecords(int totalRecords) { this.totalRecords = totalRecords; }
        
        public int getSuccessRecords() { return successRecords; }
        public void setSuccessRecords(int successRecords) { this.successRecords = successRecords; }
        
        public int getFailRecords() { return failRecords; }
        public void setFailRecords(int failRecords) { this.failRecords = failRecords; }
        
        public List<String> getSuccessFileList() { return successFileList; }
        public void setSuccessFileList(List<String> successFileList) { this.successFileList = successFileList; }
        
        public List<String> getFailedFileList() { return failedFileList; }
        public void setFailedFileList(List<String> failedFileList) { this.failedFileList = failedFileList; }
        
        public Map<String, String> getFailedReasons() { return failedReasons; }
        public void setFailedReasons(Map<String, String> failedReasons) { this.failedReasons = failedReasons; }
        
        public String getErrorMessage() { return errorMessage; }
        public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
        
        public int getMatchedCompanyCount() { return matchedCompanyCount; }
        public void setMatchedCompanyCount(int matchedCompanyCount) { this.matchedCompanyCount = matchedCompanyCount; }
        
        public int getUnmatchedCompanyCount() { return unmatchedCompanyCount; }
        public void setUnmatchedCompanyCount(int unmatchedCompanyCount) { this.unmatchedCompanyCount = unmatchedCompanyCount; }
        
        // 辅助方法
        public void addSuccessFile(String filePath, String companyName) {
            this.successFileList.add(filePath + " (" + companyName + ")");
            this.successFiles++;
        }
        
        public void addFailedFile(String filePath, String reason) {
            this.failedFileList.add(filePath);
            this.failedReasons.put(filePath, reason);
            this.failFiles++;
        }
        
        public double getSuccessRate() {
            if (totalFiles == 0) return 0.0;
            return (double) successFiles / totalFiles * 100;
        }
        
        public double getRecordSuccessRate() {
            if (totalRecords == 0) return 0.0;
            return (double) successRecords / totalRecords * 100;
        }
        
        @Override
        public String toString() {
            return String.format("BatchProcessResult{成功=%s, 文件夹='%s', 文件=%d/%d, 记录=%d/%d}", 
                success, folderPath, successFiles, totalFiles, successRecords, totalRecords);
        }
        
        /**
         * 获取处理摘要
         */
        public String getSummary() {
            StringBuilder summary = new StringBuilder();
            summary.append("=== Word文档批量处理结果 ===\n");
            summary.append("文件夹: ").append(folderPath).append("\n");
            summary.append("处理状态: ").append(success ? "成功" : "失败").append("\n");
            
            if (success) {
                summary.append("文件处理: ").append(successFiles).append("/").append(totalFiles)
                       .append(" (").append(String.format("%.1f", getSuccessRate())).append("%)\n");
                summary.append("记录处理: ").append(successRecords).append("/").append(totalRecords)
                       .append(" (").append(String.format("%.1f", getRecordSuccessRate())).append("%)\n");
                summary.append("企业匹配: ").append(matchedCompanyCount).append("个匹配成功, ")
                       .append(unmatchedCompanyCount).append("个使用原始名称\n");
            } else {
                summary.append("错误信息: ").append(errorMessage).append("\n");
            }
            
            if (!failedFileList.isEmpty()) {
                summary.append("失败文件:\n");
                for (String failedFile : failedFileList) {
                    summary.append("  - ").append(failedFile).append(": ")
                           .append(failedReasons.get(failedFile)).append("\n");
                }
            }
            
            return summary.toString();
        }
        
        /**
         * 获取文件夹名
         */
        public String getFolderName() {
            if (folderPath == null) return "未知文件夹";
            int lastSlash = folderPath.lastIndexOf("/");
            int lastBackslash = folderPath.lastIndexOf("\\");
            int lastIndex = Math.max(lastSlash, lastBackslash);
            return lastIndex >= 0 ? folderPath.substring(lastIndex + 1) : folderPath;
        }
    }
}
